#include "plotWidget.h"

#include <QPalette>
#include <QTime>
#include <QDateTime>
#include <QMap>

#include "qwt/qwt_plot_grid.h"
#include "qwt/qwt_plot_canvas.h"
#include "qwt/qwt_plot_panner.h"
#include "qwt/qwt_plot_magnifier.h"
#include "qwt/qwt_scale_div.h"
#include "qwt/qwt_scale_draw.h"
#include "qwt/qwt_picker_machine.h"
#include "qwt/qwt_scale_draw.h"
#include "qwt/qwt_plot_picker.h"
#include "qwt/qwt_plot_marker.h"
// #include "qwt/qwt_plot_curve.h"

#include "cuvre.h"
#include "histogram.h"
#include "plotData.h"
#include "plot/plotzoompicker.h"
#include "plot/plotlegend.h"

class TimeScaleDraw: public QwtScaleDraw
{
public:
    TimeScaleDraw( const QDateTime &base, bool df=false):
        baseTime( base ) , datef(df)
    {
        qDebug() << baseTime.toString("dd hh:mm:ss.zzz") << "\n";
    }
    virtual QwtText label( double v ) const
    {
        QDateTime upTime = baseTime.addMSecs( static_cast<int>( v ) );
        if (datef)
        {
            return upTime.toString("dd hh:mm:ss.zzz");
        }else{
            return upTime.toString("hh:mm:ss.zzz");
        }
    }
    void setbaseVal(QDateTime _t,bool df=false)
    {
        baseTime = _t;
        datef = df;
    };
private:
    QDateTime baseTime;
    bool datef;
};

class DoubleScaleDraw: public QwtScaleDraw
{
public:
    DoubleScaleDraw( const double &base ):
        baseval( base )
    {
    }
    virtual QwtText label( double v ) const
    {
        double upval = baseval+v;
        return QString("%1").arg(QString("%1").arg(upval,0,'f',6,QLatin1Char(' ')).toFloat());
    }
    void setbaseVal(double _v)
    {
        baseval = _v;
    };
private:
    double baseval;
};

class MyQwtPlotPicker : public QwtPlotPicker
{
public:
    explicit MyQwtPlotPicker( int xAxis, int yAxis, QwtPlotCanvas *_canvas )
        : QwtPlotPicker(xAxis,yAxis,_canvas)
        , tf(true)
    {

    };
    explicit MyQwtPlotPicker( int xAxis, int yAxis,
        RubberBand rubberBand, DisplayMode trackerMode,
        QwtPlotCanvas * _canvas)
        : QwtPlotPicker(xAxis,yAxis,rubberBand,trackerMode,_canvas)
        , tf(true)
    {
    };
    // void setTimeFlags(bool f)
    // {
    //     tf=f;
    // }
    void setbaseVal(QDateTime _t, double _v,bool df = false){
        xbaseVal = _t;
        ybaseVal = _v;
        datef = df;
        tf = true;
    };
    void setbaseVal(double _x, double _v){
        xbaseValf = _x;
        ybaseVal = _v;
        tf = false;
    };
protected:
    virtual QwtText trackerText( const QPoint &pos ) const
    {
        return trackerTextF( invTransform( pos ) );
    };
    virtual QwtText trackerTextF( const QPointF &pos ) const
    {
        QString text;

        switch ( rubberBand() )
        {
            case HLineRubberBand:
                text.sprintf( "%.4f", pos.y() );
                break;
            case VLineRubberBand:
                text.sprintf( "%.4f", pos.x() );
                break;
            case CrossRubberBand:
            {
                QString _Xtext = "";
                if (tf)
                {
                    QDateTime uptime = xbaseVal.addMSecs(static_cast<int>( pos.x() ));
                    if (datef)
                    {
                        _Xtext = uptime.toString("dd hh:mm:ss.zzz");
                    }else{
                        _Xtext = uptime.toString("hh:mm:ss.zzz");
                    }
                }else{
                    _Xtext=QString("%1").arg(xbaseValf+pos.x());
                }

                text.sprintf( "%s, %.4f", _Xtext.toStdString().c_str(), ybaseVal+pos.y() );
                break;
            }
            default:
                text.sprintf( "%.4f, %.4f", pos.x(), pos.y() );
        };
        return QwtText( text );
    }
    void move( const QPoint &pos )
    {
        QwtPlotPicker::move(pos);
    }
private:
    bool tf;
    bool datef;
    QDateTime xbaseVal;
    double xbaseValf;
    double ybaseVal;
};


PlotWidget::PlotWidget( QWidget *parent )
    : QwtPlot(parent)
{
    init();
}

PlotWidget::PlotWidget( const QwtText &title, QWidget *parent )
    : QwtPlot(title,parent)
{
    init();
}

PlotWidget::~PlotWidget()
{

}

void PlotWidget::init()
{
    // _style = QwtPlotCurve::CurveStyle::Lines;
    _style = QwtPlotCurve::Lines;
    m_Cuvre = new QList<Cuvre*>();
    m_MyHistogram = new QList<MyHistogram*>();

    this->setAutoFillBackground( true );
    // this->setPalette( QPalette( QColor( 165, 193, 228 ) ) );
    this->updateGradient(QColor( 165, 193, 228 ));

//    this->createNewCurve("Curve",QwtPlotCurve::Lines);
    // grid
    this->initgrid();
    // canvas
    this->initcanvas();
    //Axis
    this->initaxis();
    //insertLegend
    this->initLegend();
    //zoom
    this->initzoom();
    //moving
    this->initmov();
    //picker
    this->initPicker();
    //magn
    this->initMagn();
    //Interval
    // QwtScaleDiv *m_QwtScaleDiv = new QwtScaleDiv();
    // this->setAxisScaleDiv(2,*m_QwtScaleDiv);
    this->IntervalInit(-100,100,-10,10);
    //Marker
    // this->addYMarker(0.0,QString::fromLatin1("y=0"));
    // this->addXMarker(1.0 * M_PI,QString::fromLatin1("x = 1 pi"));
    // this->addXMarker(2.0 * M_PI,QString::fromLatin1("x = 2 pi"));
    this->makerInit(0,"t=0",0,"y=0");
    //scale
    this->initScaleXY();

    this->setAutoReplot(true);
    this->updateAxes();
    this->replot();

    lineColor << Qt::red << Qt::blue << Qt::green
        << Qt::magenta << Qt::yellow << Qt::cyan
        <<Qt::black;
}

void PlotWidget::updateGradient(const QColor _col)
{
    QPalette pal = this->palette();

    QLinearGradient gradient( 0, 0, 0, 1 );
    gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, _col );
    gradient.setColorAt( 1.0, _col );

    pal.setBrush( QPalette::Window, gradient );
    this->setPalette( pal );
}

void PlotWidget::initgrid()
{
    QwtPlotGrid *grid = new QwtPlotGrid();
    // grid->setMajorPen( QPen( Qt::white, 0, Qt::DotLine ) );
    grid->setMajorPen( QPen( Qt::black, 0, Qt::DotLine ) );
    // grid->setMinorPen( QPen( /*Qt::gray*/Qt::red, 0 , Qt::DotLine ) );
    // grid->setPen( QPen( Qt::white, 0, Qt::DotLine ) );
    grid->attach( this );
}

void PlotWidget::initcanvas()
{
    QPalette canvasPalette( Qt::white );
    canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
    this->canvas()->setPalette( canvasPalette );
}

void PlotWidget::initLegend()
{
    // this->insertLegend(new PlotLegend(),QwtPlot::RightLegend,-1.0);
    this->insertLegend(new PlotLegend(),QwtPlot::TopLegend,-1.0);
}

void PlotWidget::initaxis()
{
    // this->setAxisTitle(2,tr("time"));
    // this->setAxisTitle(0,tr("val"));
    this->setAxisFont(2,QFont("QFont::Courier"));
    // this->enableAxis(3,true);
    // this->enableAxis(1,true);
}

void PlotWidget::initzoom()
{
    // d_zoomer = new MyQwtPlotZoomer( this->canvas() );
    // QwtPlotZoomer *d_zoomer = new MyQwtPlotZoomer( this->canvas() );
    // MyQwtPlotZoomer *d_zoomer = new MyQwtPlotZoomer( QwtPlot::xBottom, QwtPlot::yLeft,this->canvas() );
    d_zoomer = new MyQwtPlotZoomer( QwtPlot::xBottom, QwtPlot::yLeft,dynamic_cast<QwtPlotCanvas*>(this->canvas()) );

    //Band display
    d_zoomer->setRubberBandPen( QColor( Qt::green /*Qt::red */) );
    d_zoomer->setRubberBand(QwtPlotZoomer::RectRubberBand);

    //str dispaly
    // d_zoomer->setTrackerPen( QColor( Qt::white ) );
    // d_zoomer->setTrackerPen( QColor( Qt::black ) );
    // d_zoomer->setTrackerMode(QwtPlotZoomer::AlwaysOn);
    d_zoomer->setTrackerMode(QwtPlotZoomer::AlwaysOff);
    // d_zoomer->setTrackerFont(QFont("Helvetica [Cronyx]"));

    //mouse operation
    d_zoomer->setMousePattern(QwtEventPattern::MouseSelect1,Qt::RightButton, Qt::ControlModifier );
    d_zoomer->setMousePattern(QwtEventPattern::MouseSelect1,Qt::RightButton );
    d_zoomer->setMousePattern(QwtEventPattern::MouseSelect2,Qt::MidButton, Qt::ControlModifier );
    // d_zoomer->setMousePattern(QwtEventPattern::MouseSelect3,Qt::MidButton );

    connect(d_zoomer, SIGNAL(resetcanvas()),
        this, SLOT(resetcanvas()));
}

void PlotWidget::resetcanvas()
{
    this->setBaseView();
    this->update();
}

void PlotWidget::initmov()
{
    d_panner = new QwtPlotPanner( this->canvas() );
    // d_panner->setMouseButton( Qt::MidButton );
    // d_panner->setMouseButton( Qt::RightButton );//右键移动
    d_panner->setMouseButton( Qt::LeftButton);// 左键移动
//    d_panner->setMouseButton( Qt::LeftButton, Qt::ShiftModifier );// 左键移动
    d_panner->setCursor(QCursor(Qt::OpenHandCursor));
    d_panner->setEnabled(true);
}

void PlotWidget::initPicker()
{
    // coor info display
    m_MyQwtPlotPicker = new MyQwtPlotPicker( QwtPlot::xBottom, QwtPlot::yLeft,dynamic_cast<QwtPlotCanvas*>(this->canvas()) );
    // m_MyQwtPlotPicker = new MyQwtPlotPicker( QwtPlot::xBottom, QwtPlot::yLeft,
    //     QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn,
    //     this->canvas() );
    // m_MyQwtPlotPicker->setStateMachine( new QwtPickerDragPointMachine() );
    // m_MyQwtPlotPicker->setRubberBandPen( QColor( Qt::green ) );
    // m_MyQwtPlotPicker->setRubberBandPen( QColor( Qt::red ) );
    m_MyQwtPlotPicker->setRubberBand( QwtPicker::CrossRubberBand );//时间-值显示
//    m_MyQwtPlotPicker->setRubberBand( QwtPicker::EllipseRubberBand );
    m_MyQwtPlotPicker->setTrackerMode(QwtPicker::AlwaysOn);
    m_MyQwtPlotPicker->setTrackerPen( QColor( Qt::black ) );
    m_MyQwtPlotPicker->setbaseVal(QDateTime::currentDateTime(),0.0);
}

void PlotWidget::initMagn()
{
    QwtPlotMagnifier *PM = new QwtPlotMagnifier( this->canvas() );
    PM->setMouseButton(Qt::MidButton);////使用滚轮放大/缩小
    // PM->setMouseButton(Qt::RightButton);
}
void PlotWidget::initScaleXY(bool tf)
{
    if (tf)
    {
        m_TimeScaleDraw = new TimeScaleDraw(QDateTime::currentDateTime());
        m_TimeScaleDraw->setPenWidth(1);
        this->setAxisScaleDraw(2,m_TimeScaleDraw);
    }else{
        m_DoubleScaleDrawX = new DoubleScaleDraw(0.0);
        m_DoubleScaleDrawX->setPenWidth(1);
        this->setAxisScaleDraw(2,m_DoubleScaleDrawX);
    }

    m_DoubleScaleDraw = new DoubleScaleDraw(0.0);
    m_DoubleScaleDraw->setPenWidth(1);
    this->setAxisScaleDraw(0,m_DoubleScaleDraw);
    this->updateAxes();
}

void PlotWidget::IntervalInit(double xMin, double xMax, double yMin, double yMax)
{
    QwtInterval *d_intervalX = new QwtInterval(xMin,xMax/*,QwtInterval::IncludeBorders*/);
    QwtInterval *d_intervalY = new QwtInterval(yMin,yMax/*,QwtInterval::IncludeBorders*/);
    QwtScaleDiv *_scaledivX = new QwtScaleDiv();
    _scaledivX->setInterval(*d_intervalX);
    QwtScaleDiv *_scaledivY = new QwtScaleDiv();
    _scaledivY->setInterval(*d_intervalY);
    this->setAxisScaleDiv(QwtPlot::xBottom,*_scaledivX);
    this->setAxisScaleDiv(QwtPlot::yLeft,*_scaledivY);
    this->updateAxes();
    this->update();
}

void PlotWidget::setInterval(double xMin, double xMax, double yMin, double yMax)
{
    this->setAxisScale(QwtPlot::xBottom,xMin,xMax);
    this->setAxisScale(QwtPlot::yLeft,yMin,yMax);
    this->updateAxes();
    this->update();
}

void PlotWidget::makerInit(double xValue, QString xmark,double yValue, QString ymark)
{
    initXMarker(xValue,xmark);
    initYMarker(yValue,ymark);
}

void PlotWidget::initXMarker(double xValue, QString mark)
{
    m_QwtPlotMarkerX = new QwtPlotMarker();
    m_QwtPlotMarkerX->setLabel(QwtText(mark));
    m_QwtPlotMarkerX->setLabelAlignment(Qt::AlignBottom);
    m_QwtPlotMarkerX->setLabelOrientation(Qt::Vertical);
    m_QwtPlotMarkerX->setLineStyle(QwtPlotMarker::VLine);
    // m_QwtPlotMarkerX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    m_QwtPlotMarkerX->setXValue(xValue);//该标线画在x＝xValue的位置
    m_QwtPlotMarkerX->attach(this);
}

void PlotWidget::initYMarker(double yValue, QString mark)
{
    m_QwtPlotMarkerY = new QwtPlotMarker();
    m_QwtPlotMarkerY->setLabel(QwtText(mark));
    m_QwtPlotMarkerY->setLabelAlignment(Qt::AlignLeft);
    m_QwtPlotMarkerY->setLabelOrientation(Qt::Horizontal);
    m_QwtPlotMarkerY->setLineStyle(QwtPlotMarker::HLine);//线的方向
    // m_QwtPlotMarkerY->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    m_QwtPlotMarkerY->setYValue(yValue);//标尺线画在y＝0的位置
   // m_QwtPlotMarker->setAxes(2,0);
//    m_QwtPlotMarkerY->setTitle(tr("QwtPlotMarker"));
//    m_QwtPlotMarkerY->setValue(-10,10);
//    m_QwtPlotMarker->setVisible(true);
    m_QwtPlotMarkerY->attach(this);
}

void PlotWidget::AddXMarker(double xValue, QString mark)
{
	// qDebug()<<"\n"<<mark<<"\n";
    QwtPlotMarker *_QwtPlotMarkerX = new QwtPlotMarker();
    _QwtPlotMarkerX->setLabel(QwtText(mark));
    // _QwtPlotMarkerX->setLabel(mark);
    _QwtPlotMarkerX->setLabelAlignment(Qt::AlignBottom);
    // _QwtPlotMarkerX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
    _QwtPlotMarkerX->setLabelOrientation(Qt::Vertical);
    _QwtPlotMarkerX->setLineStyle(QwtPlotMarker::VLine);
    // _QwtPlotMarkerX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    _QwtPlotMarkerX->setXValue(xValue);//该标线画在x＝xValue的位置
    _QwtPlotMarkerX->attach(this);
}
void PlotWidget::AddYMarker(double yValue, QString mark)
{
    QwtPlotMarker *_QwtPlotMarkerY = new QwtPlotMarker();
    _QwtPlotMarkerY->setLabel(QwtText(mark));
    _QwtPlotMarkerY->setLabelAlignment(Qt::AlignLeft);
    _QwtPlotMarkerY->setLabelOrientation(Qt::Horizontal);
    _QwtPlotMarkerY->setLineStyle(QwtPlotMarker::HLine);//线的方向
    // _QwtPlotMarkerY->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    _QwtPlotMarkerY->setYValue(yValue);//标尺线画在y＝yValue的位置
    _QwtPlotMarkerY->attach(this);
}


void PlotWidget::setXMarker(double xValue, QString xmark)
{
    m_QwtPlotMarkerX->setYValue(xValue);
    if (""!=xmark)
    {
        m_QwtPlotMarkerX->setLabel(QwtText(xmark));
    }
    this->update();
}

void PlotWidget::setYMarker(double yValue, QString ymark)
{
    m_QwtPlotMarkerY->setXValue(yValue);
    if (""!=ymark)
    {
        m_QwtPlotMarkerY->setLabel(QwtText(ymark));
    }
    this->update();
}

void PlotWidget::createNewCurve(QString title,QwtPlotCurve::CurveStyle style,QColor _col)
{
    Cuvre* cuvre = new Cuvre(title,style) ;
    // cuvre->setPen(QColor(Qt::blue));
    cuvre->setPen(_col);
    cuvre->setSymbolPen(_col/*QColor(Qt::black)*/);
    cuvre->setSymbolBrush(Qt::SolidPattern);
    cuvre->setSymbolSize(QSize( 2, 2 ));
    cuvre->setSymbolStyle(QwtSymbol::Ellipse);
    // cuvre->setSymbolStyle(QwtSymbol::XCross);
    // cuvre->setSymbolStyle(QwtSymbol::Style::Ellipse);
    cuvre->attach(this);

    m_Cuvre->append(cuvre);
};

void PlotWidget::drawItemsDatas(QString _title,QMap<QDateTime,qreal> itemdatas)
{
    clearCurve();
    this->setAutoReplot(true);
    if (itemdatas.empty())
    {
        return;
    }
    QDateTime _st = QDateTime::fromString("2050-01-01 00:00:00.000","yyyy-MM-dd hh:mm:ss.zzz");
    QDateTime _et = QDateTime::fromString("1900-01-01 00:00:00.000","yyyy-MM-dd hh:mm:ss.zzz");
    qreal _yMin = 999999999.0;
    qreal _yMax = -999999999;
    for (QMap<QDateTime,qreal>::iterator it = itemdatas.begin(); it != itemdatas.end(); it++)
    {
        if (_st>it.key())
        {
            _st = it.key();
        }
        if (_et<it.key())
        {
            _et = it.key();
        }
        if (_yMin>it.value())
        {
            _yMin=it.value();
        }
        if (_yMax<it.value())
        {
            _yMax=it.value();
        }
    }
    if (_st>_et||_yMin>_yMax)
    {
        return;
    }

    QDateTime _tval = _st;
    qint64 _xtval = 0;
    qint64 _xIVal = 0;
    getAxisTimeVal(_st,_et,_tval,_xtval,_xIVal);

    qreal _dval = 0.0;
    qreal _yIVal = 0.0;
    getAxisVal(_yMin,_yMax,_dval,_yIVal);

    _bv._tf = 1;
    _bv._td = _tval.date();
    _bv._tt = _tval.time();
    _bv._val = _dval;
    _bv._with = _xIVal;
    _bv._height = _yIVal;
    this->setBaseView();

    createNewCurve(_title,_style);
    this->addCurveInterval(_title,20,20);
    int curve_flag = findCurve(_title);
    for (QMap<QDateTime,qreal>::iterator it = itemdatas.begin(); it != itemdatas.end(); it++)
    {
        addData(curve_flag,it.key().toMSecsSinceEpoch()-_xtval,it.value()-_dval);
        // addData(_title,it.key().toMSecsSinceEpoch()-_xtval,it.value()-_dval);
    }

    this->update();
};

void PlotWidget::drawItemsDatas(QMap<QString,QMap<QDateTime,qreal> > itemdatas)
{
    clearCurve();
    this->setAutoReplot(true);
    if (itemdatas.empty())
    {
        return;
    }
    //get min and max time,get min and max val
    QDateTime _st = QDateTime::fromString("2050-01-01 00:00:00.000","yyyy-MM-dd hh:mm:ss.zzz");
    QDateTime _et = QDateTime::fromString("1900-01-01 00:00:00.000","yyyy-MM-dd hh:mm:ss.zzz");
    qreal _yMin = 999999999.0;
    qreal _yMax = -999999999;
    // qDebug() << QString("start get val limit curT=%1\n").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
    for (QMap<QString,QMap<QDateTime,qreal> >::iterator it_p = itemdatas.begin();it_p != itemdatas.end();it_p++)
    {
        for (QMap<QDateTime,qreal>::iterator it = it_p.value().begin(); it != it_p.value().end(); it++)
        {
            if (_st>it.key())
            {
                _st = it.key();
            }
            if (_et<it.key())
            {
                _et = it.key();
            }
            if (_yMin>it.value())
            {
                _yMin=it.value();
            }
            if (_yMax<it.value())
            {
                _yMax=it.value();
            }
        }
    }
    // qDebug() << QString("end get val limit curT=%1\n").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
    if (_st>_et||_yMin>_yMax)
    {
        return;
    }
    //
    QDateTime _tval = _st;
    qint64 _xtval = 0;
    qint64 _xIVal = 0;
    getAxisTimeVal(_st,_et,_tval,_xtval,_xIVal);

    qreal _dval = 0.0;
    qreal _yIVal = 0.0;
    getAxisVal(_yMin,_yMax,_dval,_yIVal);

    _bv._tf = 1;
    _bv._td = _tval.date();
    _bv._tt = _tval.time();
    _bv._val = _dval;
    _bv._with = _xIVal;
    _bv._height = _yIVal;
    this->setBaseView();

    //draw
    int _index = 0;
    qsrand(255);
    // qDebug() << QString("start createNewCurve curT=%1\n").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
    for (QMap<QString,QMap<QDateTime,qreal> >::iterator it_p = itemdatas.begin();it_p != itemdatas.end();it_p++)
    {
        createNewCurve(it_p.key(),_style,lineColor[_index%lineColor.size()]);
        _index++;
        this->addCurveInterval(it_p.key(),20,20);
        int curve_flag = findCurve(it_p.key());
        for (QMap<QDateTime,qreal>::iterator it = it_p.value().begin(); it != it_p.value().end(); it++)
        {
            // addData(it_p.key(),it.key().toMSecsSinceEpoch()-_xtval,it.value()-_dval);
            addData(curve_flag,it.key().toMSecsSinceEpoch()-_xtval,it.value()-_dval);
        }
    }
    // qDebug() << QString("end createNewCurve curT=%1\n").arg(QTime::currentTime().toString("hh:mm:ss.zzz"));
    this->update();
};

void PlotWidget::drawItemsDatas(QList<DataItem> itemdatas)
{
    clearCurve();
    this->setAutoReplot(true);

    if (itemdatas.empty())
    {
        return;
    }
    QTime _st = itemdatas[0].getMinQTime();
    QTime _et = itemdatas[0].getMaxQTime();
    qreal _yMin = itemdatas[0].getMinData();
    qreal _yMax = itemdatas[0].getMaxData();

    for (int i = 1; i < itemdatas.size(); i++)
    {
        if (_st>itemdatas[i].getMinQTime())
        {
            _st = itemdatas[i].getMinQTime();
        }
        if (_et<itemdatas[i].getMaxQTime())
        {
            _et = itemdatas[i].getMaxQTime();
        }
        if (_yMin>itemdatas[i].getMinData())
        {
            _yMin = itemdatas[i].getMinData();
        }
        if (_yMax<itemdatas[i].getMaxData())
        {
            _yMax = itemdatas[i].getMaxData();
        }
    }

    QTime _tval = _st;
    int _xtval = 0;
    int _xIVal = 0;
    getAxisTimeVal(_st,_et,_tval,_xtval,_xIVal);

    qreal _dval = 0.0;
    qreal _yIVal = 0.0;
    getAxisVal(_yMin,_yMax,_dval,_yIVal);

    _bv._tf = 2;
    _bv._tt = _tval;
    _bv._val = _dval;
    _bv._with = _xIVal;
    _bv._height = _yIVal;
    this->setBaseView();

    for (int i = 0; i < itemdatas.size(); i++)
    {
        QString _curvetitle = itemdatas[i].getName();
        createNewCurve(_curvetitle,_style);
        QPen pen(QColor(255-255*(int)(i%255),(int)255*(i%255),0,128));
        pen.setWidth(3);
        this->setCurvePen(_curvetitle,pen);
        int curve_flag = findCurve(_curvetitle);
        this->addCurveInterval(_curvetitle,20,20);
        for (int j = 0; j < itemdatas[i].size();j++)
        {
            QTime _tt = itemdatas[i].value(j).getTime();
            int _x = 60*60*1000*_tt.hour()+60*1000*_tt.minute()+1000*_tt.second()+_tt.msec();
            // addData(_curvetitle,_x-_xtval,itemdatas[i].value(j).getData()-_dval);
            addData(curve_flag,_x-_xtval,itemdatas[i].value(j).getData()-_dval);
        }
    }

    this->update();
}

void PlotWidget::clear()
{
    clearCurve();
};

void PlotWidget::drawItemsData(DataItem itemdata)
{
    clearCurve();
    this->setAutoReplot(true);

    QTime _st = itemdata.getMinQTime();
    QTime _et = itemdata.getMaxQTime();

    QTime _tval = _st;
    int _xtval = 0;
    int _xIVal = 0;
    getAxisTimeVal(_st,_et,_tval,_xtval,_xIVal);

    qreal _yMin = itemdata.getMinData();
    qreal _yMax = itemdata.getMaxData();
    qreal _dval = 0.0;
    qreal _yIVal = 0.0;
    getAxisVal(_yMin,_yMax,_dval,_yIVal);

    _bv._tf = 2;
    _bv._tt = _tval;
    _bv._val = _dval;
    _bv._with = _xIVal;
    _bv._height = _yIVal;
    this->setBaseView();

    QString _curveName = itemdata.getName();
    createNewCurve(_curveName,_style);
    this->addCurveInterval(_curveName,20,20);
    int curve_flag = findCurve(_curveName);
    for (int i = 0; i < itemdata.size();i++)
    {
        QTime _tt = itemdata.value(i).getTime();
        int _x = 60*60*1000*_tt.hour()+60*1000*_tt.minute()+1000*_tt.second()+_tt.msec();
        // addData(_curveName,_x-_xtval,itemdata.value(i).getData()-_dval);
        addData(curve_flag,_x-_xtval,itemdata.value(i).getData()-_dval);
    }

    this->update();
}

void PlotWidget::getAxisTimeVal(QDateTime _st, QDateTime _et, QDateTime &_tval,  qint64 &_xtInt, qint64 &_xIVal)
{
    qint64 _xMin = _st.toMSecsSinceEpoch();
    qint64 _xMax = _et.toMSecsSinceEpoch();
    qint64 _xVal = _xMax - _xMin;

    _xtInt = _xMin + _xVal/2;
    int size = (QString("%1").arg(_xVal)).size()-1;

    _xtInt = qPow(10,size)*qRound(_xtInt*qPow(10,0-size));
    _xIVal = 2*qMax(qAbs(_xMax-_xtInt),qAbs(_xtInt-_xMin));

    _tval = _st;
    _tval = _tval.addMSecs(_xtInt-_xMin);
};

void PlotWidget::getAxisTimeVal(QTime _st, QTime _et, QTime &_tval,  int &_xtInt, int &_xIVal)
{
    // int _xMin = 60*60*1000*_st.hour()
    //     +60*1000*_st.minute()
    //     +1000*_st.second()
    //     +_st.msec();
    // int _xMax = 60*60*1000*_et.hour()
    //     +60*1000*_et.minute()
    //     +1000*_et.second()
    //     +_et.msec();
    int _xMin = QTime().msecsTo(_st);
    int _xMax = QTime().msecsTo(_et);
    int _xVal = (int)(_xMax - _xMin);

    _xtInt = _xMin + _xVal/2;
    int size = (QString("%1").arg(_xVal)).size()-1;

    _xtInt = qPow(10,size)*qRound(_xtInt*qPow(10,0-size));
    _xIVal = 2*qMax(qAbs(_xMax-_xtInt),qAbs(_xtInt-_xMin));

    _tval = _st;
    _tval = _tval.addMSecs(_xtInt-_xMin);
}

void PlotWidget::getAxisVal(qreal _min, qreal _max, qreal &_dval, qreal &_yval)
{
    _yval = _max - _min;
    if (_yval<=0)
    {
        _dval = _min;
        _yval = 2*qAbs(_min-qRound(_dval));
        if (0.0==_dval)
        {
            _yval = 1;
        }else{
            int pos = qrealMaxPos(_dval);
            pos = pos>0?(pos-1):pos;
            _dval = qPow(10,pos)*qRound(_dval*qPow(10,0-pos));
            if(_min==_dval)
                _yval = qPow(10,pos-1)*qCeil(2*qAbs(_dval)*qPow(10,0-pos+1));
            else
            _yval = qPow(10,pos-1)*qCeil(2*qAbs(_min-_dval)*qPow(10,0-pos+1));
        }
        return;
    }

    _dval = _min + _yval*0.5;

    int pos = qrealMaxPos(_yval);
    pos = pos>0?(pos-1):pos;
    _dval = qPow(10,pos)*qRound(_dval*qPow(10,0-pos));
    _yval = qPow(10,pos-1)*qCeil(2*qMax(qAbs(_max-_dval),qAbs(_dval-_min))*qPow(10,0-pos+1));
    if (_min==_dval||_max==_dval)
    {
        _dval = _min+qAbs(_max-_min)*0.5;
    }
}

int PlotWidget::qrealMaxPos(qreal _val)
{
    QString _str = QString("%1").arg(qAbs(_val),0,'f');
    QStringList _strList= _str.split(".", QString::SkipEmptyParts);
    int pos = 0;
    if (1==_strList.size())
    {
        if('0'!=_strList[0][0])
        {
            pos = _strList[0].size();
        }
    }else if (2==_strList.size())
    {
        if('0'!=_strList[0][0])
        {
            pos = _strList[0].size();
        }else{
            for (int i = 0; i < _strList[1].size(); i++)
            {
                if ('0'!=_strList[1][i])
                {
                    pos = -1-i;
                    break;
                }
            }
        }
    }else{
        qDebug() << "cann't sprif this qreal str!\n";
    }

    // qDebug() << "_val="<<_val<<","<<"_str"<<_str<<","<<"pos="<<pos<<"\n";
    return pos;
}

void PlotWidget::setBaseView()
{
    switch(_bv._tf)
    {
        case 1:
        {
            QDateTime _dt(_bv._td,_bv._tt);
            m_TimeScaleDraw->setbaseVal(_dt,true);
            m_DoubleScaleDraw->setbaseVal(_bv._val);
			m_MyQwtPlotPicker->setbaseVal(_dt,_bv._val,true);
            // m_MyQwtPlotPicker->setTimeFlags( true );//时间-值显示
            this->setXMarker(_dt.toMSecsSinceEpoch(),QString("x=%1").arg(_dt.toString("dd hh:mm:ss.zzz")));
            this->setYMarker(_bv._val,QString("y=%1").arg(_bv._val));
            this->setInterval(-_bv._with*0.75,_bv._with*0.75,-_bv._height*0.75,_bv._height*0.75);
        }
            break;
        case 2:
        {
            // int _xtval = 60*60*1000*_bv._tt.hour()
            // +60*1000*_bv._tt.minute()
            // +1000*_bv._tt.second()
            // +_bv._tt.msec();
            // int _xtval = QTime().msecsTo(_bv._tt);
            QDateTime _dt(QDate::currentDate(),_bv._tt);
            m_TimeScaleDraw->setbaseVal(_dt,false);
            m_DoubleScaleDraw->setbaseVal(_bv._val);
			m_MyQwtPlotPicker->setbaseVal(_dt,_bv._val,false);
            // m_MyQwtPlotPicker->setTimeFlags( true );//时间-值显示
            this->setXMarker(_dt.toMSecsSinceEpoch(),QString("x=%1").arg(_bv._tt.toString("hh:mm:ss.zzz")));
            this->setYMarker(_bv._val,QString("y=%1").arg(_bv._val));
            this->setInterval(-_bv._with*0.75,_bv._with*0.75,-_bv._height*0.75,_bv._height*0.75);
        }
            break;
        case 3:
        {
            m_DoubleScaleDrawX->setbaseVal(_bv._valx);
            m_DoubleScaleDraw->setbaseVal(_bv._val);
			m_MyQwtPlotPicker->setbaseVal(_bv._valx,_bv._val);
            // m_MyQwtPlotPicker->setTimeFlags( false );//值-值显示
            this->setXMarker(_bv._valx,QString("x=%1").arg(_bv._valx));
            this->setYMarker(_bv._val,QString("y=%1").arg(_bv._val));
            this->setInterval(-_bv._with*0.6,_bv._with*0.6,-_bv._height*0.25,_bv._height*1.25);
        }
            break;
        default:
            break;
    }
}

void PlotWidget::resetBackground(QColor _col)
{
    this->updateGradient(_col);
    this->update();
}

void PlotWidget::resetCrossColor(QColor _col)
{
    for(int i=0; i<m_Cuvre->size(); i++){
        setCurveSymbolPen(m_Cuvre->value(i)->getTitle(),_col);
    }
}

void PlotWidget::resetItemColor(QColor _col)
{
    for(int i=0; i<m_Cuvre->size(); i++){
        setCurveColor(m_Cuvre->value(i)->getTitle(),_col);
    }
}

void PlotWidget::resetItemDrawStyle(QString _sty)
{
    if ("Lines" == _sty)
    {
        _style = QwtPlotCurve::Lines;
        // _style = QwtPlotCurve::CurveStyle::Lines;
    }else if ("Sticks" == _sty)
    {
        _style = QwtPlotCurve::Sticks;
        // _style = QwtPlotCurve::CurveStyle::Sticks;
    }else if("Steps" == _sty){
        // qDebug() << "PlotWidget::resetItemDrawStyle\n";
        _style = QwtPlotCurve::Steps;
        // _style = QwtPlotCurve::CurveStyle::Steps;
    }else{
        _style = QwtPlotCurve::Lines;
        // _style = QwtPlotCurve::CurveStyle::Lines;
    }

    for(int i=0; i<m_Cuvre->size(); i++){
        setCurveStyle(m_Cuvre->value(i)->getTitle(),_style);
    }
}

void PlotWidget::removeCurve(QString title)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->detach();
    m_Cuvre->removeAt(flags);
    this->update();
}

void PlotWidget::drawHistogram(QString _title,QMap<QString,int> datas)
{
    clearHistogram();
	// this->setAxisTitle(2,tr("type"));
	this->setAxisTitle(0,tr("count"));
    // this->setAxisFont(2,QFont("QFont::Courier"));
    initScaleXY(false);

    int _maxvalx = 0;
    int _maxvaly = 0;

    QMap<QString,int>::iterator it=datas.begin();
    while(it!=datas.end())
    {
        if (it.value()<=0)
        {
            it++;
            continue;
        }
        if (_maxvaly<it.value())
        {
            _maxvaly=it.value();
        }
        _maxvalx++;
        it++;
    }

    _maxvalx = _maxvalx<2?2:_maxvalx;
    _maxvaly = _maxvaly<2?2:_maxvaly;
     // qDebug()<<"_maxvalx="<<_maxvalx<<","<<"_maxvaly="<<_maxvaly<<"\n";
    _bv._tf = 3;
    _bv._valx = _maxvalx/2;
    _bv._val = 0;
    _bv._with = _maxvalx;
    _bv._height = _maxvaly;
    this->setBaseView();
    // makerInit(_bv._valx,QString("x=%1").arg(_bv._valx),_bv._val,QString("y=%1").arg(_bv._val));

    this->createNewHistogram(_title,QwtPlotHistogram::UserStyle);
    int _index = 0;
    it=datas.begin();
    QString _typeStr = "evttype=";

    int curve_flag = findHistogram(_title);
    while(it!=datas.end())
    {
		// qDebug()<<"\n" << it.key() <<","<<it.value() <<","<<_index<<"\n";
        if (it.value()>0)
        {
            MyInterval m_MyInterval(it.value(),_index-_bv._valx,_index-_bv._valx+0.4);
            // qDebug() <<"_index="<<_index<<","<<"it.key()="<<it.key()<<"it.value()="<<it.value()<<"\n";
            // this->addDataToHistogram(_title
            //     ,QwtIntervalSample(m_MyInterval.getvalue(),m_MyInterval.getmin(),m_MyInterval.getmax())
            //     ,QColor(200,100,200));
            this->addDataToHistogram(curve_flag
                ,QwtIntervalSample(m_MyInterval.getvalue(),m_MyInterval.getmin(),m_MyInterval.getmax())
                ,QColor(200,100,200));
            _typeStr+=(it.key()+";");
            //this->AddXMarker(_index-_bv._valx+0.2,QString("%1=%2").arg(it.key()).arg(it.value()));
    		//this->setXMarker(_index-_bv._valx+0.2,QString("%1=%2").arg(it.key()).arg(it.value()));
            _index++;
		}
        it++;
    }
    this->setAxisTitle(2,_typeStr);
    this->setAxisFont(2,QFont("QFont::Courier"));
    // this->transform(0,-_maxvaly);
    // d_panner->moveCanvas(0,-_maxvaly/2);
    this->update();
}

void PlotWidget::createNewHistogram(QString title,QwtPlotHistogram::HistogramStyle style)
{
    MyHistogram *myHistogram = new MyHistogram(title,style);
    myHistogram->attach(this);
    m_MyHistogram->append(myHistogram);
}

void PlotWidget::removeHistogram(QString title)
{
    int flags = findHistogram(title);
    if(-1==flags)
        return;
    m_MyHistogram->value(flags)->detach();
    m_MyHistogram->removeAt(flags);
    this->update();
}

void PlotWidget::addDataToHistogram(QString title, const QwtIntervalSample val, const QColor color)
{
    int flags = findHistogram(title);
    if(-1==flags)
        return;
    m_MyHistogram->value(flags)->addData(val,color);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::addDataToHistogram(int curveFlag, const QwtIntervalSample val, const QColor color)
{
    m_MyHistogram->value(curveFlag)->addData(val,color);
}
int PlotWidget::findHistogram(const QString title)
{
    int flags = -1;
    for(int i=0; i<m_MyHistogram->size(); i++){
        if(title == m_MyHistogram->value(i)->getTitle()){
            flags = i;
            break;
        }
    }

    return flags;
}

void PlotWidget::setCurveStyle(QString title,QwtPlotCurve::CurveStyle style)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setStyle(style);
}

void PlotWidget::setCurveColor(QString title,QColor color )
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setPen(color);
}

void PlotWidget::setCurveBaseline(QString title, double basline)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setBaseline(basline);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::setCurveBrush(QString title, QBrush brush)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setBrush(brush);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::setCurvePen(QString title, QPen pen)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setPen(pen);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::setCurveSymbolStyle(QString title,QwtSymbol::Style style)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setSymbolStyle(style);
}

void PlotWidget::setCurveSymbolBrush(QString title,
                    QBrush brush)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setSymbolBrush(brush);
}

void PlotWidget::setCurveSymbolPen(QString title,
                    QPen pen)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setSymbolPen(pen);
}

void PlotWidget::setCurveSymbolSize(QString title,
                    QSize size)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setSymbolSize(size);
}

void PlotWidget::addPoint(QString title,QPointF point)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->addPoint(point);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::addData(QString title,const double x, const double y)
{
    this->addPoint(title,QPointF(x,y));
}

void PlotWidget::addData(int curveFlag,const double x, const double y)
{
    m_Cuvre->value(curveFlag)->addPoint(QPointF(x,y));
}

void PlotWidget::addCurveInterval(QString title, const int from, const int to)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->addInterval(from,to);
    if(this->autoReplot())
        this->update();
}

void PlotWidget::setCurveMove( QString title, const double x_Move, const double y_Move)
{
    int flags = findCurve(title);
    if(-1==flags)
        return;
    m_Cuvre->value(flags)->setCurveMove(x_Move,y_Move);
    if(this->autoReplot())
        this->update();
}

int PlotWidget::findCurve(const QString title)
{
    int flags = -1;
    for(int i=0; i<m_Cuvre->size(); i++){
        if(title == m_Cuvre->value(i)->getTitle()){
            flags = i;
            break;
        }
    }

    return flags;
}

void PlotWidget::clearCurve()
{
    for (int i = 0; i < m_Cuvre->size(); i++)
    {
        m_Cuvre->value(i)->detach();
    }
    m_Cuvre->clear();
    d_zoomer->clearZoomStack();
}

void PlotWidget::clearHistogram()
{
    for (int i = 0; i < m_MyHistogram->size(); i++)
    {
        m_MyHistogram->value(i)->detach();
    }
    m_MyHistogram->clear();
    d_zoomer->clearZoomStack();
}

bool PlotWidget::autoUpdate()
{
    return QwtPlot::autoReplot();
}

void PlotWidget::setAutoUpdate(bool flags)
{
    QwtPlot::setAutoReplot(flags);
}

void PlotWidget::update()
{
    this->setSamples();
    QwtPlot::updateAxes();
    // QwtPlot::updateCanvasMargins();
    // QwtPlot::updateLegend();
//    this->canvas()->replot();
    this->replot();
    QwtPlot::update();
}

void PlotWidget::setSamples()
{
    if(!m_Cuvre->empty()){
        for(int i=0; i<m_Cuvre->size(); i++)
        {
            m_Cuvre->value(i)->setSamples();
        }
    }

    if(!m_MyHistogram->empty()){
        for(int i=0; i<m_MyHistogram->size(); i++)
        {
            m_MyHistogram->value(i)->setSamples();
        }
    }

    // if(!m_MYMultiBarChart->empty()){
    //     for(int i=0; i<m_MYMultiBarChart->size(); i++)
    //     {
    //         m_MYMultiBarChart->value(i)->setSamples();
    //     }
    // }
}

void PlotWidget::setPlotTilte(QString Title)
{
    this->setTitle(Title);
}

void PlotWidget::setPlotFooter(QString footer)
{
    this->setFooter(footer);
}

void PlotWidget::setAxisTitleX(QString xTitle)
{
    this->setAxisTitle(QwtPlot::xBottom,xTitle);
}

void PlotWidget::setAxisTitleY(QString yTitle)
{
    this->setAxisTitle(QwtPlot::yLeft,yTitle);
}
